﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
using System.Threading;

namespace SimpleUnitity.Log
{
    public static class LogHelper
    {
        private static List<ELogLevel> loglevels = new List<ELogLevel>();

        static LogHelper()
        {
            InitLog(ELogLevel.Info);
        }

        #region SyncWrite
        public static void InitLog(ELogLevel level)
        {
            loglevels.Clear();
            for (int i = (int)level; i < (int)ELogLevel.Off; i++)
            {
                loglevels.Add((ELogLevel)i);
            }
        }

        public static void Write(ILog logging, string message, ELogLevel level)
        {
            if (loglevels.Contains(level))
            {
                logging.Write(message, level);
            }
        }

        public static void Track(ILog logging, string message)
        {
            Write(logging, message, ELogLevel.Track);
        }

        public static void Debug(ILog logging, string message)
        {
            Write(logging, message, ELogLevel.Debug);
        }

        public static void Info(ILog logging, string message)
        {
            Write(logging, message, ELogLevel.Info);
        }

        public static void Error(ILog logging, string message)
        {
            Write(logging, message, ELogLevel.Error);
        }

        public static void Warn(ILog logging, string message)
        {
            Write(logging, message, ELogLevel.Warn);
        } 
        #endregion

        #region AsyncWrite
        class SyncLogItem
        {
            public string Message { get; set; }

            public ELogLevel LogLevel { get; set; }

            public ILog Logging { get; set; }
        }

        static readonly object syncObject = new object();
        static Thread thread = null;

        static LinkedList<SyncLogItem> messageList = new LinkedList<SyncLogItem>();

        static void WriteLog()
        {
            SyncLogItem item = null;
            while (true)
            {
                while (messageList.First!= null)
                {
                    lock (syncObject)
                    {
                        item = messageList.First.Value;
                        messageList.RemoveFirst();
                    }
                    if (loglevels.Contains(item.LogLevel))
                    {
                        try
                        {
                            item.Logging.Write(item.Message, item.LogLevel);
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex);
                        }
                    }
                }
                thread.Suspend();
            }
        }

        public static void AsyncWrite(ILog logging, string message, ELogLevel level)
        {
            if (thread == null)
            {
                lock (syncObject)
                {
                    if (thread == null)
                    {
                        thread = new Thread(WriteLog);
                        thread.IsBackground = true;
                        thread.Start();
                    }
                }
            }
            if (logging != null)
            {
                lock (syncObject)
                {
                    messageList.AddLast(new SyncLogItem() { Logging = logging, LogLevel = level, Message = message });
                }
            }
            if ((thread.ThreadState & ThreadState.Suspended) != 0)
            {
                thread.Resume();
            }
        }

        public static void AsyncTrack(ILog logging, string message)
        {
            AsyncWrite(logging, message, ELogLevel.Track);
        }

        public static void AsyncDebug(ILog logging, string message)
        {
            AsyncWrite(logging, message, ELogLevel.Debug);
        }

        public static void AsyncInfo(ILog logging, string message)
        {
            AsyncWrite(logging, message, ELogLevel.Info);
        }

        public static void AsyncError(ILog logging, string message)
        {
            AsyncWrite(logging, message, ELogLevel.Error);
        }

        public static void AsyncWarn(ILog logging, string message)
        {
            AsyncWrite(logging, message, ELogLevel.Warn);
        } 

        #endregion
    }
}
